package com.example.bledemo;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.provider.Settings;
import android.location.LocationManager;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AlertDialog;

import java.util.ArrayList;
import java.util.List;

import android.util.Log;
import android.content.Intent;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanSettings;

import com.example.bledemo.adapter.BleDeviceAdapter;

public class BleScanActivity extends AppCompatActivity {
    private static final int REQUEST_CODE_BLE_SCAN_PERMISSIONS = 2001;
    private BluetoothLeScanner bleScanner;
    private ScanCallback scanCallback;
    private boolean isScanning = false;
    private BleDeviceAdapter deviceAdapter;
    private List<ScanResult> scanResults = new ArrayList<>();
    private Button btnStartScan;
    private TextView tvScanStatus;

    private String[] getRequiredPermissions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            return new String[]{
                    Manifest.permission.BLUETOOTH_ADVERTISE,
                    Manifest.permission.BLUETOOTH_CONNECT,
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.BLUETOOTH,
                    Manifest.permission.BLUETOOTH_ADMIN,
            };
        } else {
            return new String[]{
                    Manifest.permission.BLUETOOTH,
                    Manifest.permission.BLUETOOTH_ADMIN,
                    Manifest.permission.ACCESS_FINE_LOCATION
            };
        }
    }

    private boolean hasAllPermissions() {
        for (String perm : getRequiredPermissions()) {
            if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    private void requestBlePermissions() {
        ActivityCompat.requestPermissions(this, getRequiredPermissions(), REQUEST_CODE_BLE_SCAN_PERMISSIONS);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ble_scan);

        tvScanStatus = findViewById(R.id.tv_scan_status);
        btnStartScan = findViewById(R.id.btn_start_scan);
        RecyclerView rvDevices = findViewById(R.id.rv_ble_devices);

        rvDevices.setLayoutManager(new LinearLayoutManager(this));
        deviceAdapter = new BleDeviceAdapter(scanResults);
        rvDevices.setAdapter(deviceAdapter);

        BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
        BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
        bleScanner = bluetoothAdapter.getBluetoothLeScanner();

        btnStartScan.setOnClickListener(v -> {
//            if (!hasAllPermissions()) {
//                requestBlePermissions();
//                return;
//            }
            if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
                Toast.makeText(this, "请先打开蓝牙", Toast.LENGTH_SHORT).show();
                return;
            }
            if (bleScanner == null) {
                Toast.makeText(this, "设备不支持BLE扫描", Toast.LENGTH_SHORT).show();
                return;
            }
            if (!isLocationEnabled()) {
                Toast.makeText(this, "请先开启系统位置服务，否则无法扫描BLE设备", Toast.LENGTH_LONG).show();
                startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                return;
            }
            if (!isScanning) {
                startScan();
            } else {
                stopScan();
            }
        });
    }

    private boolean isLocationEnabled() {
        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        return locationManager != null && locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    private void startScan() {
        Log.i("BLE_SCAN", "准备开始扫描");
        if (isScanning) return;
        scanResults.clear();
        deviceAdapter.notifyDataSetChanged();
        tvScanStatus.setText("状态: 扫描中...");
        isScanning = true;
        btnStartScan.setText("停止扫描");
        
        // 优化扫描设置，捕获更多类型的广播
        ScanSettings scanSettings = new ScanSettings.Builder()
                .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)  // 低延迟模式
                .setReportDelay(0)  // 立即报告
                .setNumOfMatches(ScanSettings.MATCH_NUM_MAX_ADVERTISEMENT)  // 最大匹配数
                .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)  // 激进匹配模式
                .build();
        
        // 不设置扫描过滤器，接收所有广播包
        List<ScanFilter> scanFilters = new ArrayList<>();
        
        scanCallback = new ScanCallback() {
            @Override
            public void onScanResult(int callbackType, ScanResult result) {
                if (!containsDevice(result)) {
                    scanResults.add(result);
                    deviceAdapter.notifyItemInserted(scanResults.size() - 1);
                }
                
                // 简化日志打印，避免UI线程阻塞
                String name = result.getDevice().getName();
                if (name == null) name = "(无名设备)";
                String address = result.getDevice().getAddress();
                int rssi = result.getRssi();
                
                // 从 ScanRecord 中获取设备名称（更准确）
                String scanRecordName = null;
                if (result.getScanRecord() != null) {
                    scanRecordName = result.getScanRecord().getDeviceName();
                }
                
                Log.i("BLE_SCAN", "设备信息 - 设备对象名称: '" + name + "', ScanRecord名称: '" + scanRecordName + "', 地址: " + address + ", RSSI: " + rssi);
                
                // 检查是否是我们应用的广播
                boolean isOurBroadcast = false;
                String ourBroadcastInfo = "";
                
                if (result.getScanRecord() != null) {
                    android.util.SparseArray<byte[]> manufacturerData = result.getScanRecord().getManufacturerSpecificData();
                    if (manufacturerData != null && manufacturerData.size() > 0) {
                        for (int i = 0; i < manufacturerData.size(); i++) {
                            int key = manufacturerData.keyAt(i);
                            byte[] data = manufacturerData.valueAt(i);
                            
                            // 检查是否是AOA广播数据 (Manufacturer ID = 65535, 31字节)
                            if (key == 65535 && data != null && data.length == 31) {
                                isOurBroadcast = true;
                                ourBroadcastInfo = " (AOA广播数据)";
                                
                                // 解析AOA广播数据
                                parseAoaBroadcastData(data, address);
                            }
                            
                            Log.i("BLE_SCAN", "ManufacturerData: Address=" + address + ", CompanyID=" + key + ", Data=" + (data == null ? "null" : bytesToHex(data)) + ", raw=" + java.util.Arrays.toString(data));
                        }
                    }
                }
                
                // 只在Logcat中打印基本信息，避免复杂字符串拼接
                Log.i("BLE_SCAN", "发现设备: " + name + ", 地址: " + address + ", RSSI: " + rssi + ourBroadcastInfo + "result:" + result.toString());
                
                // 每10个设备打印一次汇总信息，避免频繁打印
                if (scanResults.size() % 10 == 0) {
                    Log.i("BLE_SCAN", "当前已扫描到 " + scanResults.size() + " 个设备");
                }
            }

            @Override
            public void onScanFailed(int errorCode) {
                super.onScanFailed(errorCode);
                tvScanStatus.setText("状态: 扫描失败(" + errorCode + ")");
                isScanning = false;
                btnStartScan.setText("开始扫描");
                Log.e("BLE_SCAN", "扫描失败，错误码: " + errorCode);
                Toast.makeText(BleScanActivity.this, "扫描失败，错误码: " + errorCode, Toast.LENGTH_LONG).show();
            }
        };

        // 使用优化的扫描设置
        bleScanner.startScan(scanFilters, scanSettings, scanCallback);
        Log.i("BLE_SCAN", "已调用 startScan (优化模式)");
        tvScanStatus.postDelayed(this::stopScan, 15000); // 延长到15秒
    }

    private void stopScan() {
        if (isScanning && bleScanner != null && scanCallback != null) {
            bleScanner.stopScan(scanCallback);
            tvScanStatus.setText("状态: 扫描结束");
            isScanning = false;
            btnStartScan.setText("开始扫描");
            Log.i("BLE_SCAN", "已调用 stopScan");
        }
    }

    private boolean containsDevice(ScanResult result) {
        for (ScanResult r : scanResults) {
            if (r.getDevice().getAddress().equals(result.getDevice().getAddress())) {
                return true;
            }
        }
        return false;
    }

    private String bytesToHex(byte[] bytes) {
        if (bytes == null) return "null";
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    private String extractBroadcastId(String hexData) {
        try {
            // 查找 "BLE_" 的位置 (424C455F)
            int bleIndex = hexData.indexOf("424C455F");
            if (bleIndex != -1 && bleIndex + 16 <= hexData.length()) {
                // 提取 "BLE_" 后面的 8 个字符作为广播标识符的一部分
                String idHex = hexData.substring(bleIndex + 8, bleIndex + 16);
                // 将十六进制转换回字符串
                return "BLE_" + hexToString(idHex);
            }
        } catch (Exception e) {
            Log.e("BLE_SCAN", "提取广播标识符失败: " + e.getMessage());
        }
        return "未知";
    }

    // 将十六进制字符串转换为普通字符串
    private String hexToString(String hex) {
        try {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hex.length(); i += 2) {
                String hexPair = hex.substring(i, i + 2);
                int decimal = Integer.parseInt(hexPair, 16);
                sb.append((char) decimal);
            }
            return sb.toString();
        } catch (Exception e) {
            return "ERROR";
        }
    }
    
    // 解析AOA广播数据
    private void parseAoaBroadcastData(byte[] data, String address) {
        try {
            if (data.length != 31) {
                Log.w("BLE_SCAN", "AOA广播数据长度不正确: " + data.length + " 字节");
                return;
            }

            // 解析广播数据
            byte[] ignore = new byte[3];     // 忽略字段 (3字节)
            System.arraycopy(data, 0, ignore, 0, 3);

            byte[] fixedId = new byte[4];    // 固定标识 (4字节)
            System.arraycopy(data, 3, fixedId, 0, 4);

            byte[] id = new byte[3];         // ID (3字节)
            System.arraycopy(data, 7, id, 0, 3);

            byte checksum = data[10]; // 校验和 (1字节)

            byte[] cte = new byte[20];       // CTE (20字节)
            System.arraycopy(data, 11, cte, 0, 20);

            // 验证固定标识
            boolean isValidFixedId = (fixedId[0] == 0x1B && fixedId[1] == 0x03 && 
                                    fixedId[2] == 0x00 && fixedId[3] == 0x01);
            
            // 验证校验和
            byte[] dataForChecksum = new byte[7];
            System.arraycopy(fixedId, 0, dataForChecksum, 0, 4);
            System.arraycopy(id, 0, dataForChecksum, 4, 3);
            byte calculatedChecksum = calculateChecksum(dataForChecksum);
            boolean isValidChecksum = (checksum == calculatedChecksum);
            
            // 打印解析结果
            Log.i("BLE_SCAN", "=== AOA广播数据解析结果 ===");
            Log.i("BLE_SCAN", "设备地址: " + address);
            Log.i("BLE_SCAN", "忽略字段: " + bytesToHex(ignore));
            Log.i("BLE_SCAN", "固定标识: " + bytesToHex(fixedId) + " (有效: " + isValidFixedId + ")");
            Log.i("BLE_SCAN", "ID: " + bytesToHex(id));
            Log.i("BLE_SCAN", "校验和: 0x" + String.format("%02X", checksum) + " (有效: " + isValidChecksum + ")");
            Log.i("BLE_SCAN", "CTE: " + bytesToHex(cte));
            Log.i("BLE_SCAN", "================================");
            
        } catch (Exception e) {
            Log.e("BLE_SCAN", "解析AOA广播数据失败: " + e.getMessage());
        }
    }
    
    // 计算校验和 (与发送端一致)
    private byte calculateChecksum(byte[] data) {
        byte checksum = 0;
        for (byte b : data) {
            checksum ^= b;
        }
        return checksum;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_BLE_SCAN_PERMISSIONS) {
            if (hasAllPermissions()) {
                Toast.makeText(this, "权限已授予，请重新点击开始扫描", Toast.LENGTH_SHORT).show();
            } else {
                boolean someDeniedPermanently = false;
                for (int i = 0; i < permissions.length; i++) {
                    if (grantResults[i] != PackageManager.PERMISSION_GRANTED &&
                        !ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) {
                        someDeniedPermanently = true;
                        break;
                    }
                }
                if (someDeniedPermanently) {
                    new AlertDialog.Builder(this)
                        .setTitle("权限申请")
                        .setMessage("部分权限被永久拒绝，请在设置中手动开启“附近设备”权限，否则无法扫描BLE设备。")
                        .setPositiveButton("去设置", (dialog, which) -> {
                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                            intent.setData(android.net.Uri.parse("package:" + getPackageName()));
                            startActivity(intent);
                        })
                        .setNegativeButton("取消", null)
                        .show();
                } else {
                    Toast.makeText(this, "缺少必要权限，无法扫描BLE设备", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
} 